// Line of Code Counter Program
//
// for counting line of code in Java, C#, C++ and BASIC.
// 
// Edited by Charlie Gruop
// 
// By add function
// *Enable to count the code in Java.
// *Count comment and count blank space.
//
//
// Original by toughman_net@hotmail.com

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace Trustbridge.SourceCodeLineCounter
{
    public partial class Form1 : Form
    {
        int widthFix = 0;
        int maximumHistory = 5;
        public Form1()
        {
            InitializeComponent();
            widthFix = SystemInformation.VerticalScrollBarWidth + SystemInformation.Border3DSize.Width * 3;
            cmbSearchPattern.Items.Add("*.java");
            cmbSearchPattern.Items.Add("*.cs");
            cmbSearchPattern.Items.Add("*.vb");
            cmbSearchPattern.Items.Add("*.cs|*.vb");
            cmbSearchPattern.Items.Add("*.c");
            cmbSearchPattern.Items.Add("*.h");
            cmbSearchPattern.Items.Add("*.c|*.h");
            cmbSearchPattern.SelectedIndex = 0;

            lblNoFilesFound.BackColor = listView1.BackColor;
        }

        private void btnBrowse_ButtonClick(object sender, EventArgs e)
        {
            btnSelectFolder_Click(null, null);
        }
        private void btnRecount_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(lblFolder.Text))
            {
                CountFiles(lblFolder.Text);
            }
        }
        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.Description = "Select a folder which contains the files you wish to line count.   " + (chkIncludeSubfolders.Checked ? "All subfolders and files will" : "Only the files contained within the selected folder will") + " be included while only searching for " + cmbSearchPattern.SelectedItem.ToString() + ".";
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                CountFiles(folderBrowserDialog1.SelectedPath);
            }
        }

        private void CountFiles(string FolderPath)
        {
            if (FolderPath.ToUpper() == "C:\\")
            {
                return;
            }

            // Add this folder path to the drop down list
            AddToFolderHistory(FolderPath);

            int totalCounter = 0;
            int fileCounter = 0;
            FileInfo file;
            StreamReader reader;
            bool error = false;
            bool dontCount = false;
            bool autoGeneratedCode = false;

            Cursor = Cursors.WaitCursor;
            lblNoFilesFound.Text = "Searching...";
            lblNoFilesFound.Visible = true;
            lblFolder.Text = FolderPath;
            listView1.Items.Clear();
            toolStripStatuslblLines.Text = "0 lines";
            this.Refresh();

            DirectoryInfo dir = new DirectoryInfo(FolderPath);
            //FileInfo[] files = dir.GetFiles(cmbSearchPattern.SelectedItem.ToString(), (chkIncludeSubfolders.Checked ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));
            string[] searchPatternSplit = cmbSearchPattern.SelectedItem.ToString().Split(new char[] { '|' });
            foreach (string pattern in searchPatternSplit)
            {
                FileInfo[] files = dir.GetFiles(pattern, (chkIncludeSubfolders.Checked ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));

                listView1.BeginUpdate();
                toolStripProgressBar1.Value = 0;
                toolStripProgressBar1.Maximum = files.Length;
                toolStripProgressBar1.Visible = true;

                if (files.Length > 0)
                {
                    lblNoFilesFound.Text = "Counting...";
                    lblNoFilesFound.Refresh();
                }

                for (int i = 0; i < files.Length; i++)
                {

                    file = (FileInfo)files.GetValue(i);
                    toolStripProgressBar1.Value = i;

                    if (!mnuIncludeDesigner.Checked)
                    {
                        // excludes the VS 2005 Designer file
                        if (file.FullName.ToLower().Contains(".designer."))
                        {
                            continue;
                        }
                    }

                    fileCounter = 0;
                    error = false;
                    dontCount = false;
                    autoGeneratedCode = false;
                    try
                    {
                        string s;
                        reader = file.OpenText();
                        s = reader.ReadLine();
                        while (s != null)
                        {
                            dontCount = false;

                            if (!autoGeneratedCode)
                            {
                                // Remove Tabs
                                s = s.Replace("\t", "");

                                // Comments
                                if (!mnuIncludeComments.Checked)
                                {
                                    if (s.StartsWith("//") || (s.StartsWith("'") || s.StartsWith ("/*")))
                                    {
                                        dontCount = true;
                                    }
                                }
                                // Blank lines
                                if (!mnuIncludeBlankLines.Checked)
                                {
                                    if (s.Equals("") || s== "")
                                    {
                                        dontCount = true;
                                    }
                                }
                            }
                            // Autogenerated Code
                            if (!mnuIncludeAutoGenerated.Checked)
                            {
                                if (autoGeneratedCode)
                                {
                                    if (s.Contains("#endregion") || s.Contains("#End Region"))
                                    {
                                        dontCount = true;
                                        autoGeneratedCode = false;
                                    }
                                }
                                else if (s == "#region Windows Form Designer generated code" || s == "#Region \" Windows Form Designer generated code \"")
                                {
                                    dontCount = true;
                                    autoGeneratedCode = true;
                                }
                            }

                            if (!dontCount && !autoGeneratedCode)
                            {
                                fileCounter++;
                            }

                            s = reader.ReadLine();
                        }
                        reader.Close();
                    }
                    catch
                    {
                        // An error here could be because of no access to file
                        // or directory access is denied, or it could be a
                        // general exception
                        error = true;
                    }

                    totalCounter += fileCounter;
                    listView1.Items.Add(new ListViewItem(new string[] { file.DirectoryName, file.Name, (error ? "Error" : fileCounter.ToString()) }));
                }
                listView1.EndUpdate();
                toolStripStatuslblLines.Text = totalCounter.ToString() + " lines";
                toolStripStatuslblLines.Tag = totalCounter;
                toolStripProgressBar1.Visible = false;
                if (listView1.Items.Count == 0)
                {
                    lblNoFilesFound.Visible = true;
                    lblNoFilesFound.Text = "No files found";
                }
                else
                {
                    lblNoFilesFound.Visible = false;
                }
                Cursor = Cursors.Default;
            }
        }

        private void AddToFolderHistory(string FolderPath)
        {
            // Check if folder exists in the list
            ToolStripItem[] searchItems = btnBrowse.DropDownItems.Find(FolderPath, true);
            if (searchItems.Length == 0)
            {
                // Doesn't exist
                if (btnBrowse.DropDownItems.Count == maximumHistory)
                {
                    btnBrowse.DropDownItems.RemoveAt(maximumHistory-1);
                }

                ToolStripMenuItem item = new ToolStripMenuItem();
                item.Name = item.Text = FolderPath;
                item.Click += new EventHandler(FolderHistory_Click);
                this.btnBrowse.DropDownItems.Insert(0, item);
            }
            else
            {
                // Does exist so just move to the top
                this.btnBrowse.DropDownItems.Insert(0, searchItems[0]);
            }
        }
        private void FolderHistory_Click(object sender, EventArgs e)
        {
            // History item has been selected so move to the top
            lblFolder.Text = ((ToolStripMenuItem)sender).Text;
            this.btnBrowse.DropDownItems.Insert(0, ((ToolStripMenuItem)sender));
            CountFiles(lblFolder.Text);
        }

        private void listView1_SizeChanged(object sender, EventArgs e)
        {
            listView1.Columns[0].Width = listView1.Columns[1].Width = (listView1.Width - listView1.Columns[2].Width - widthFix) / 2;
        }

        private void toolStripMenuItemAdd_Click(object sender, EventArgs e)
        {
            if (toolStripStatuslblLines.Tag == null)
            {
                return;
            }

            ToolStripMenuItem item = new ToolStripMenuItem();
            item.Text = toolStripStatuslblLines.Text + " > " + lblFolder.Text;
            item.Tag = toolStripStatuslblLines.Tag;
            toolStripGrouping.DropDownItems.Add(item);

            UpdateGroupingTotal();
        }

        private void toolStripMenuItemClear_Click(object sender, EventArgs e)
        {
            int count = toolStripGrouping.DropDownItems.Count;
            for (int i = 4; i < count; i++)
            {
                toolStripGrouping.DropDownItems.RemoveAt(4);
            }
            UpdateGroupingTotal();
        }
        private void UpdateGroupingTotal()
        {
            int total = 0;
            ToolStripMenuItem item;
            for (int i = 4; i < toolStripGrouping.DropDownItems.Count; i++)
            {
                item = (ToolStripMenuItem)toolStripGrouping.DropDownItems[i];
                if (item.Tag != null)
                {
                    total += Convert.ToInt32(item.Tag);
                }
            }
            toolStripMenuItemTotal.Text = "Total " + total.ToString() + " lines";
        }

        private void mnuExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void chkIncludeSubfolders_Click(object sender, EventArgs e)
        {
            mnuIncludeSubfolders.Checked = chkIncludeSubfolders.Checked;
        }
        private void mnuIncludeSubfolders_Click(object sender, EventArgs e)
        {
            chkIncludeSubfolders.Checked = mnuIncludeSubfolders.Checked;
        }

        private void mnuCopyToClipboard_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Searching " + lblFolder.Text + (chkIncludeSubfolders.Checked ? " and all sub directories" : "") + " for " + cmbSearchPattern.SelectedItem.ToString());
            sb.AppendLine("Auto Generated Code: " + (mnuIncludeAutoGenerated.Checked ? "Included" : "Not included"));
            sb.AppendLine("Blank Lines: " + (mnuIncludeBlankLines.Checked ? "Included" : "Not included"));
            sb.AppendLine("Comments: " + (mnuIncludeComments.Checked ? "Included" : "Not included"));
            sb.AppendLine("Visual Studio Designer Files: " + (mnuIncludeDesigner.Checked ? "Included" : "Not included"));
            sb.AppendLine("");
            foreach (ListViewItem item in listView1.Items)
            {
                sb.AppendLine(item.SubItems[0].Text + item.SubItems[1].Text + "\t\t" + item.SubItems[2].Text + " lines");
            }
            sb.AppendLine("");
            sb.AppendLine("Total lines counted: " + toolStripStatuslblLines.Text);
            Clipboard.SetText(sb.ToString());
        }

    }
}